package wci.backend.interpreter.executors;

import java.util.List;

import wci.backend.interpreter.Executor;
import wci.intermediate.ICodeNode;
import wci.intermediate.icodeimpl.ICodeKeyImpl;

/**
 * 非优化本SELECT执行器，直接按照前面遍历节点思路扩散开来的
 * @author yifan.cby
 */
public class RudimentSelectExecutor extends StatementExecutor {

	public RudimentSelectExecutor(Executor parent) {
		super(parent);
	}

	@Override
	public Object execute(ICodeNode node) {
		//参见图7-7，CASE的节点分布
		List<ICodeNode> selectChildren = node.getChildren();
		ICodeNode exprNode = selectChildren.get(0);
		// 计算CASE表达式
		ExpressionExecutor expressionExecutor = new ExpressionExecutor(this);
		Object selectValue = expressionExecutor.execute(exprNode);
		//根据表达式值找到一个可匹配的分支，找到就执行此分支后的语句
		ICodeNode selectedBranchNode = searchBranches(selectValue,
				selectChildren);
		if (selectedBranchNode != null) {
			ICodeNode stmtNode = selectedBranchNode.getChildren().get(1);
			StatementExecutor statementExecutor = new StatementExecutor(this);
			statementExecutor.execute(stmtNode);
		}
		++executionCount; //CASE虽然有一大片，但最后只会选择一条分支
		return null;
	}
	//查找与此selectValue相匹配的分支
	private ICodeNode searchBranches(Object selectValue,
			List<ICodeNode> selectChildren) {
		for (int i = 1; i < selectChildren.size(); ++i) {
			ICodeNode branchNode = selectChildren.get(i);
			if (searchConstants(selectValue, branchNode)) {
				return branchNode;
			}
		}
		return null;
	}
	//找case分支比如1 : stmt 的1
    private boolean searchConstants(Object selectValue, ICodeNode branchNode)
    {
    	//还是看图7-7，看常量节点的存储
        ICodeNode constantsNode = branchNode.getChildren().get(0);
        List<ICodeNode> constantsList = constantsNode.getChildren();
        if (selectValue instanceof Integer) {
            for (ICodeNode constantNode : constantsList) {
                int constant = (Integer) constantNode.getAttribute(ICodeKeyImpl.VALUE);
 
                if (((Integer) selectValue) == constant) {
                    return true; 
                }
            }
        }
        else {
            for (ICodeNode constantNode : constantsList) {
                String constant = (String) constantNode.getAttribute(ICodeKeyImpl.VALUE);
 
                if (((String) selectValue).equals(constant)) {
                    return true; 
                }
            }
        }
        return false; 
    }
}
